package com.maidshop.elasticsearch.service.impl;

import com.maidshop.animation.service.AnimationService;
import com.maidshop.common.utils.StringUtils;
import com.maidshop.elasticsearch.ESRepository;
import com.maidshop.elasticsearch.domain.AnimationEs;
import com.maidshop.elasticsearch.service.ElasticsearchService;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
public class ElasticsearchImpl implements ElasticsearchService {

    @Resource
    private ElasticsearchRestTemplate template;

    @Resource
    private ESRepository esRepository;

    @Resource
    private AnimationService animationService;

    @Override
    public int save(AnimationEs animationEs) {
        template.save(animationEs);
        return 0;
    }

    @Override
    public AnimationEs getById(Long id) {
        return null;
    }

    @Override
    public int deleteById(Long id) {
        esRepository.deleteById(id);
        return 0;
    }

    @Override
    public List<AnimationEs> findByNameOrTypeOrIntro(String text) {
        // 查询全部数据
//        QueryBuilder builder = QueryBuilders.matchAllQuery();
        // 精确查询 = (需要类型是keyword)
//        TermQueryBuilder builder = QueryBuilders.termQuery("name", "此花亭奇谭");
        // match匹配，会把查询条件进行分词，然后再进行匹配,可以指定分词器
//        QueryBuilder builder = QueryBuilders.matchQuery("name", "此花亭奇谭");
//        QueryBuilder builder = QueryBuilders.matchQuery("name", "奇巧").analyzer("ik_smart");
        // 模糊查询
//        QueryBuilder builder = QueryBuilders.matchQuery("intro", "旅行");
        // 多条件构造
        BoolQueryBuilder builder = QueryBuilders.boolQuery();
        // 并且 and
//        builder.must(QueryBuilders.matchQuery("name", "奇"));
//        builder.must(QueryBuilders.matchQuery("intro", "司机"));
        // 或者 or
        builder.should(QueryBuilders.matchQuery("name", text));
        builder.should(QueryBuilders.matchQuery("type", text));
        builder.should(QueryBuilders.matchQuery("intro", text));
        // 构建分页
        Pageable pageable = PageRequest.of(0, 10);
        NativeSearchQuery query = new NativeSearchQueryBuilder()
                .withQuery(builder)
                .withPageable(pageable)
                .withSort(SortBuilders.fieldSort("_score").order(SortOrder.DESC))
                .withHighlightFields(
                        new HighlightBuilder.Field("name").preTags("<span style='color:red;'>").postTags("</span>"),
                        new HighlightBuilder.Field("type").preTags("<span style='color:red;'>").postTags("</span>")
                )
                .build();
        SearchHits<AnimationEs> search = template.search(query, AnimationEs.class);
        List<AnimationEs> list = new ArrayList<>();
        // 单独设置高亮
        for (SearchHit<AnimationEs> s : search) {
            AnimationEs animationEs = s.getContent();
            List<String> name = s.getHighlightField("name");
            if (name != null && name.size() > 0) {
                animationEs.setName(name.get(0));
            }
            List<String> type = s.getHighlightField("type");
            if (type != null && type.size() > 0) {
                animationEs.setType(type.get(0));
            }
            list.add(animationEs);
        }
        // 直接转换，但不会有高亮效果
//        Stream<SearchHit<AnimationEs>> searchHitStream = search.get();
//        List<AnimationEs> list = searchHitStream.map(SearchHit::getContent).collect(Collectors.toList());
        return list;
    }

    @Override
    public int initElasticsearch() {
        // 查询全部动画数据
        List<AnimationEs> list = animationService.findAllAnimationEs();
        for (AnimationEs animationEs : list) {
            template.save(animationEs);
        }
        return 0;
    }

    @Override
    public void updateAnimationEs(AnimationEs animationEs) {
        esRepository.save(animationEs);
    }
}
